// 函数返回对象时,有几种返回方式可供选择,可以返回 指向对象的引用/指向对象的const引用/const对象

//              指向const对象的引用
// 使用const的引用旨在于提高效率,但是何时采用这种方式存在一些限制,如果函数返回传递给他的对象,可以返回引用来提高效率

// version 1
// Vector Max(const Vector & v1,const Vector & v2){
//     if (v1.magval() > v2.magval())
//     {
//         return v1;
//     }else return v2;
// }
//
//
// version 2
// const Vector & Max(const Vector &v1, const Vector &v2){
//   if (v1.magval() > v2.magval())
//     {
//         return v1;
//     }else return v2;
// }

// 如果调用了第1个版本的函数,返回一个类,那么这个类必然要用复制构造函数,像下面第2个版本函数,返回对象的引用,它就不会存在这个问题。

// 要使用这样引用的返回,有几个需要注意的地方:
//      1.返回对象要调用复制构造函数，而返回引用不会。因此第2个版本的函数做的工作更少，效率更高。
//      2.引用指向的对象应在调用函数执行时存在。在这个例子中引用指向v1和v2,他们都是在调用函数中定义的，因此满足这样的条件。
//      3.v一和v二都被声明为const的引用，因此返回类型必须为const，这样才匹配。

//              返回指向非const对象的引用
// 两种常见的返回非const对象的情形时，重载赋值运算符以及重载与cout的一起使用的<<运算符。因为返回的cout对象可变。前者这样做旨在提高效率，而后者必须这样做。
//    operator=()用于连续赋值
//    String s1("Good stuff");
//    String s2,s3;
//  返回的就是非const对象,或者非const对象的引用
//    operator<<()的返回值用于串接输出
//    String s1("Good stuff");
//    cout << s1 << "is Coming!!\n";
//  在上述代码中，operator<<(cout, s1)的返回值成为了一个用于显示字符串is coming的对象,返回值类型必须是ostream &,而不能仅仅是ostream!
//  如果使用返回值类型ostream，将要求调用ostream类的复制构造函数,然而ostream没有公有的复制构造函数。
//  返回一个指向cout的引用，不会带来任何问题，因为cout已经在调用函数的作用域内。

//              返回对象
// 如果被返回的对象是被调用函数中的局部变量，则不应该按饮用方式返回它,因为在被调用函数执行完成时，局部对象将调用其析构函数，因此当控制权回到调用函数时引用指向的对象将不再存在。
// 在这种情况下存在调用复制钩子函数来创建被返回对象的开销，然而这是无法避免的。


// 总之,如果方法或函数要返回局部对象，则应返回对象，而不是指向对象的引用，在这种情况下，将使用复制构造函数来生成返回的对象。
// 如果方法或函数要返回一个没有公有复制构造函数的类的对象(比如说ostream)，它必须返回一个指向这种对象的引用。
// 最后有些方法和函数如重载的复制运算符可以返回，对象也可以返回指向对象的引用，在这种情况下应该首选引用，因为它的效率更高。